import { expect, it } from 'vitest'
import { compile, transformImportAndExport } from './compiler'

const FileName = 'test.ts'
it('matches inline snapshot', () => {
  expect(compile(`
  import a from 'bb/bb-plugin';
import j from './bb1';
import { ab, cd } from './bb2';
import b, { c, d } from './bb3';
console.log(a,j, ab, cd, b, c,d)
export const dd = 1;
export default {
    a: 1,
    b: 2
};

`, FileName)).toMatchInlineSnapshot(`
  "
    import a from 'bb/bb-plugin';
    const j = window.__modules__['bb1'].default;
    const { ab, cd } = window.__modules__['bb2'];
    const b = window.__modules__['bb3'].default;
    console.log(a,j, ab, cd, b, c,d)
    const dd = 1;
    __export__('test.ts', 'dd', dd);
    const __default__ = {
  a: 1,
  b: 2
  };
    __export__('test.ts', 'default', __default__);

  "
`)
})

it('transforms relative import statements to window.__modules__', () => {
  const source = `
    import a from './a';
    import { b, c } from './b';
  `
  expect(transformImportAndExport(source, 'test.ts')).toMatchInlineSnapshot(`
    "
        const a = window.__modules__['a'].default;
        const { b, c } = window.__modules__['b'];
      "
  `)
})

it('transforms relative import statements with alias to window.__modules__', () => {
  const source = `
    import a from './a';
    import { b as bb, c as cc, d } from './b';
  `
  expect(transformImportAndExport(source, 'test.ts')).toMatchInlineSnapshot(`
    "
        const a = window.__modules__['a'].default;
        const { b: bb, c: cc, d } = window.__modules__['b'];
      "
  `)
})

it('transforms export statements to __export__ calls', () => {
  const source = `
    export const a = 1;
    export default { b: 2 };
  `
  expect(transformImportAndExport(source, 'test.ts')).toMatchInlineSnapshot(`
      "
          const a = 1;
          __export__('test.ts', 'a', a);
          const __default__ = {
      b: 2
      };
          __export__('test.ts', 'default', __default__);
        "
    `)
})

it('does not transform absolute import statements', () => {
  const source = `
    import a from 'a';
    import { b, c } from 'b';
  `
  expect(transformImportAndExport(source, 'test.ts')).toMatchInlineSnapshot(`
      "
          import a from 'a';
          import { b, c } from 'b';
        "
    `)
})

it('does not transform non-export statements', () => {
  const source = `
    const a = 1;
    const b = { c: 2 };
  `
  expect(transformImportAndExport(source, 'test.ts')).toMatchInlineSnapshot(`
      "
          const a = 1;
          const b = { c: 2 };
        "
    `)
})

it('transforms export function statements to __export__ calls', () => {
  const source = `
    export function myFunction() { 
      return 1; 
    }
  `
  expect(transformImportAndExport(source, 'test.ts')).toMatchInlineSnapshot(`
    "
        function myFunction() {return 1;}
        __export__('test.ts', 'myFunction', myFunction);
      "
  `)
})

it('transforms export function statements with arguments to __export__ calls', () => {
  const source = `
    export function myFunction(a, b, c) { 
      return a + b + c; 
    }
    export function myFunction2(a) { 
      return a; 
    }
     export function myFunction3() { 
      return 3; 
    }
  `
  expect(transformImportAndExport(source, 'test.ts')).toMatchInlineSnapshot(`
    "
        function myFunction(a,b,c) {return a + b + c;}
        __export__('test.ts', 'myFunction', myFunction);
        function myFunction2(a) {return a;}
        __export__('test.ts', 'myFunction2', myFunction2);
        function myFunction3() {return 3;}
        __export__('test.ts', 'myFunction3', myFunction3);
      "
  `)
})

it('transforms export class statements to __export__ calls', () => {
  const source = `
    export class MyClass { 
      constructor() { 
        this.value = 1; 
      } 
    }
  `
  const transformedSource = transformImportAndExport(source, 'test.ts')
  expect(transformedSource).toMatchInlineSnapshot(`
    "
        class MyClass {constructor() { 
    this.value = 1; 
    }}
        __export__('test.ts', 'MyClass', MyClass);
      "
  `)
})

it('transforms export default function statements to __export__ calls', () => {
  const source = `
    export default function myDefaultFunction() { 
      function myInnerFunction() { return 1; }
      return 2; 
     }
  `
  const transformedSource = transformImportAndExport(source, 'test.ts')
  expect(transformedSource).toMatchInlineSnapshot(`
    "
        const __default__ = function myDefaultFunction() { 
    function myInnerFunction() { return 1; }
    return 2; 
    };
        __export__('test.ts', 'default', __default__);
      "
  `)
})

it('transforms export default class statements to __export__ calls', () => {
  const source = `
    export default class MyDefaultClass { 
      constructor() { this.value = 2; } 
     }
  `
  const transformedSource = transformImportAndExport(source, 'test.ts')
  expect(transformedSource).toMatchInlineSnapshot(`
    "
        const __default__ = class MyDefaultClass { 
    constructor() { this.value = 2; } 
    };
        __export__('test.ts', 'default', __default__);
      "
  `)
})

it('transforms export multi-line arrow function statements to __export__ calls', () => {
  const source = `
    export const myFunction = () => {
        const value = 1;
        return value;
    }
  `
  const transformedSource = transformImportAndExport(source, 'test.ts')
  expect(transformedSource).toMatchInlineSnapshot(`
    "
        const myFunction = () => {
    const value = 1;
    return value;
    };
        __export__('test.ts', 'myFunction', myFunction);
      "
  `)
})

it('transforms export default arrow function statements to __export__ calls', () => {
  const source = `
    export default () => {
        const value = 1;
        return value;
    }
  `
  const transformedSource = transformImportAndExport(source, 'test.ts')
  expect(transformedSource).toMatchInlineSnapshot(`
    "
        const __default__ = () => {
    const value = 1;
    return value;
    };
        __export__('test.ts', 'default', __default__);
      "
  `)
})

it('builds import graph for relative import statements', () => {
  const source = `
    import a from './a';
    import { b, c } from './b';
  `
  const importGraph = {}
  transformImportAndExport(source, 'test.ts', importGraph)
  expect(importGraph).toEqual({
    'test.ts': [
      'a',
      'b',
    ],
  })
})

it('does not build import graph for absolute import statements', () => {
  const source = `
    import a from 'a';
    import { b, c } from 'b';
  `
  const importGraph = {}
  transformImportAndExport(source, 'test.ts', importGraph)
  expect(importGraph).toEqual({})
})
